using System;

using TrueCode.Core.Aspects;

namespace TrueCode.DependencyManager.Interface
{
  public class TypedValue
  {
    private readonly Type _type;
    private readonly object _value;

    public TypedValue( [NotNull] object arg )
    {
      if( arg == null ) throw new ArgumentNullException( "arg" );

      _type = arg.GetType();
      _value = arg;
    }

    public TypedValue( [NotNull] Type type, object value )
    {
      if( type == null ) throw new ArgumentNullException( "type" );

      _type = type;
      _value = value;
    }

    public Type Type
    {
      get { return _type; }
    }

    public object Value
    {
      get { return _value; }
    }
  }

  public static class TypedValueExtensions
  {
    public static TypedValue As< T >( this object arg )
    {
      var targetType = typeof( T );
      if( arg != null && !targetType.IsAssignableFrom( arg.GetType() ) )
      {
        var exc = new ArgumentException( "Object cannot be assigned to specified type", "arg" );
        exc.Data.Add( "Target type", targetType );
        exc.Data.Add( "Real type", arg.GetType() );
        throw exc;
      }

      return new TypedValue( targetType, arg );
    }
  }
}